use crate::common::hdc_error::{HdcError, HdcErrorKind};
use log::info;
use ylong_runtime::{
    io::{AsyncReadExt, AsyncWriteExt},
    net::{SplitReadHalf, SplitWriteHalf, TcpStream},
};

use super::task_message::TaskMessage;

pub struct TcpConnect {
    rd: SplitReadHalf,
    wr: SplitWriteHalf,
}

impl TcpConnect {
    pub fn new(stream: TcpStream) -> Self {
        let (rd, wr) = stream.into_split();
        Self { rd, wr }
    }

    pub async fn read_frame(&mut self) -> Result<Vec<u8>, HdcError> {
        let mut buff = Vec::<u8>::new();
        if (self.rd.read_to_end(&mut buff).await).is_err() {
            return Err(HdcError::new(HdcErrorKind::HdcConnectionReset, "read filed.".to_owned()));
        }
        Ok(buff)
    }

    pub async fn read_msg(&mut self) -> Result<TaskMessage, HdcError> {
        let mut buff = vec![0_u8; 512 * 1024 + 40];
        buff.resize(512 * 1024 + 40, 0);
        // read_exact 是读满缓冲
        // match self.rd.read_exact(&mut buff).await {
        // read 是读取数据
        match self.rd.read(&mut buff).await {
            Ok(0) => {
                let msg = "recv len 0, is close".to_owned();
                log::error!("{msg}");
                Err(HdcError::new(HdcErrorKind::HdcClose, msg))
            }
            Ok(n) => {
                // log::info!("read size {}", n);
                // buff.resize(n, 0);
                buff.truncate(n);
                let msg = TaskMessage::from_be_bytes(&buff)?;
                Ok(msg)
            }
            // Ok(_) => {
            //     let msg = TaskMessage::from_be_bytes(&buff)?;
            //     Ok(msg)
            // }
            Err(_) => {
                let msg = "read filed.".to_owned();
                log::error!("{msg}");
                Err(HdcError::new(HdcErrorKind::HdcConnectionReset, msg))
            }
        }
    }

    pub async fn read_data(&mut self) -> Result<(usize, [u8; 1024]), HdcError> {
        let mut buff = [0u8; 1024];
        match self.rd.read(&mut buff).await {
            Ok(n) => Ok((n, buff)),
            Err(_) => {
                Err(HdcError::new(HdcErrorKind::HdcConnectionReset, "read filed.".to_owned()))
            }
        }
    }

    pub async fn write_data(&mut self, buf: &[u8]) -> Result<(), HdcError> {
        if (self.wr.write_all(buf).await).is_err() {
            return Err(HdcError::new(HdcErrorKind::HdcOther, "write_all filed".to_owned()));
        }
        Ok(())
    }

    pub async fn write_message(&mut self, msg: TaskMessage) -> Result<(), HdcError> {
        let buf = msg.to_vec();
        if (self.wr.write_all(buf.as_slice()).await).is_err() {
            return Err(HdcError::new(HdcErrorKind::HdcOther, "write_all filed".to_owned()));
        }
        let _ = self.wr.flush().await;
        Ok(())
    }
}

impl Drop for TcpConnect {
    fn drop(&mut self) {
        ylong_runtime::block_on(async {
            let _ = self.wr.shutdown().await;
        });
        info!("shutdown");
    }
}
